/*
 * Copyright (c) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef HI_DBG_LOG_H
#define HI_DBG_LOG_H

#include <stdio.h>
#include "hi_str_util.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
    debug log level.
*/
#define HI_DLEV_NONE        0 // disable
#define HI_DLEV_ERR         1 // error
#define HI_DLEV_WARN        2 // warning
#define HI_DLEV_INFO        3 // informational
#define HI_DLEV_DBG         4 // debug normal
#define HI_DLEV_VERB        5 // debug vervose
#define HI_DLEV_BUTT        6

/**
    log on special level.

    color: E=red, W=yellow, I=default, D=green, V=gray
*/
#define LOGE(format, ...) LOG_WITH_FLF(HI_DLEV_ERR, "\033[;31m" "%s[%d](%s): " format "\033[0m", ##__VA_ARGS__)
#define LOGW(format, ...) LOG_WITH_FLF(HI_DLEV_WARN, "\033[;35m" "%s[%d](%s): " format "\033[0m", ##__VA_ARGS__)
#define LOGI(format, ...) LOG_ONLY(HI_DLEV_INFO, format, ##__VA_ARGS__)
#define LOGD(format, ...) LOG_WITH_FLF(HI_DLEV_DBG, "\033[;32m" "%s[%d](%s): " format "\033[0m", ##__VA_ARGS__)
#define LOGV(format, ...) LOG_WITH_FLF(HI_DLEV_VERB, "\033[2m" "%s[%d](%s): " format "\033[0m", ##__VA_ARGS__)

#define DOLOGE(cmd) DOLOG_WITH_FLF(HI_DLEV_ERR, "\033[;31m", (cmd))
#define DOLOGW(cmd) DOLOG_WITH_FLF(HI_DLEV_ERR, "\033[;35m", (cmd))
#define DOLOGI(cmd) DOLOG_NO_COLOR(HI_DLEV_ERR, (cmd))
#define DOLOGD(cmd) DOLOG_WITH_FLF(HI_DLEV_ERR, "\033[;32m", (cmd))
#define DOLOGV(cmd) DOLOG_WITH_FLF(HI_DLEV_ERR, "\033[2m", (cmd))

/**
    log with file/name.
*/
#define LOG_ONLY(lev, format, ...) do { \
    if (g_hiDbgLev >= (lev)) { \
        printf(format, ##__VA_ARGS__); \
    } \
}   while (0)

/**
    log with file/name/function.
*/
#define LOG_WITH_FLF(lev, format, ...) do { \
    if (g_hiDbgLev >= (lev)) { \
        printf(format, HiPathName(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__); \
    } \
}   while (0)

/**
    log with file/name.
*/
#define DOLOG_NO_COLOR(lev, cmd) do { \
    if (g_hiDbgLev >= (lev)) { \
        (cmd); \
    } \
}   while (0)

/**
    log with file/name.
*/
#define DOLOG_WITH_FLF(lev, color, cmd) do { \
    if (g_hiDbgLev >= (lev)) { \
        printf(color "%s[%d](%s): ", HiPathName(__FILE__), __LINE__, __FUNCTION__); \
        (cmd); \
        printf("\033[0m"); \
    } \
}   while (0)

/**
    Check ret, return when FAIL.
*/
#define HI_CHK_RET(ret, format, ...) do { \
    if ((ret) != 0) { \
        LOGE(format, ##__VA_ARGS__); \
        return ret; \
    } \
}   while (0)

/**
    Check ret, return when FAIL.
*/
#define HI_CHK_WRET(ret, format, ...) do { \
    if ((ret) != 0) { \
        LOGW(format, ##__VA_ARGS__); \
        return ret; \
    } \
}   while (0)

/**
    Check ret, goto label when FAIL.
*/
#define HI_CHK_GOTO(ret, label, format, ...) do { \
    if ((ret) != 0) { \
        LOGE(format, ##__VA_ARGS__); \
        goto label; \
    } \
}   while (0)

/**
    Check ret, goto label when FAIL.
*/
#define HI_CHK_WGOTO(ret, label, format, ...) do { \
    if ((ret) != 0) { \
        LOGW(format, ##__VA_ARGS__); \
        goto label; \
    } \
}   while (0)

/**
    Check exp, return when exp true.
*/
#define HI_EXP_RET(exp, retVal, format, ...) do { \
    if (exp) { \
        LOGE(format, ##__VA_ARGS__); \
        return (retVal); \
    } \
}   while (0)
#define HI_EXP_RET_NONE(exp, format, ...) do { \
    if (exp) { \
        LOGE(format, ##__VA_ARGS__); \
        return; \
    } \
}   while (0)

/**
    Check exp, return when exp true.
*/
#define HI_EXP_WRET(exp, retVal, format, ...) do { \
    if (exp) { \
        LOGW(format, ##__VA_ARGS__); \
        return (retVal); \
    } \
}   while (0)
#define HI_EXP_WRET_NONE(exp, format, ...) do { \
    if (exp) { \
        LOGW(format, ##__VA_ARGS__); \
        return; \
    } \
}   while (0)

/**
    Check exp, LOG when exp true.
*/
#define HI_EXP_LOGE(exp, format, ...) do { \
    if (exp) { \
        LOGE(format, ##__VA_ARGS__); \
    } \
}   while (0)
#define HI_EXP_LOGW(exp, format, ...) do { \
    if (exp) { \
        LOGE(format, ##__VA_ARGS__); \
    } \
}   while (0)

/**
    Check exp, goto label when exp true.
*/
#define HI_EXP_GOTO(exp, label, format, ...) do { \
    if (exp) { \
        LOGE(format, ##__VA_ARGS__); \
        goto label; \
    } \
}   while (0)

/**
    Check exp, goto label when exp true.
*/
#define HI_EXP_WGOTO(exp, label, format, ...) do { \
    if (exp) { \
        LOGW(format, ##__VA_ARGS__); \
        goto label; \
    } \
}   while (0)

/**
    Check exp, exec cmdExp and goto label when exp true.
*/
#define HI_EXP_CMD_GOTO(exp, cmdExp, label, format, ...) do { \
    if (exp) { \
        LOGE(format, ##__VA_ARGS__); \
        (cmdExp); \
        goto label; \
    } \
}   while (0)

/**
    Check exp, exec cmdExp and goto label when exp true.
*/
#define HI_EXP_CMD_WGOTO(exp, cmdExp, label, format, ...) do { \
    if (exp) { \
        LOGW(format, ##__VA_ARGS__); \
        (cmdExp); \
        goto label; \
    } \
}   while (0)

/**
    debug level.
*/
extern int g_hiDbgLev;

/**
    set level.
*/
void HiSetDbgLev(int lev);

#ifdef __cplusplus
}
#endif

#endif // HI_DBG_LOG_H
